﻿using XmlStudio.DataLayer;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Diagnostics;
using XmlStudio.Interfaces;
using System.Text;
using System.Xml.XPath;
using XmlStudio.Models;
using XmlStudio.Utilities;

namespace XmlStudio.Tests {
    /// <summary>
    ///This is a test class for BigXmlReaderTest and is intended
    ///to contain all BigXmlReaderTest Unit Tests
    ///</summary>
    [TestClass()]
    public class BigXmlReaderTest {
        #region Fields
        private TestContext testContextInstance;
        #endregion

        #region Properties
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext {
            get {
                return testContextInstance;
            }
            set {
                testContextInstance = value;
            }
        }
        #endregion

        #region Additional test simpleTypes
        [AssemblyInitialize()]
        public static void AssemblyInitialize(TestContext testContext) {
        }

        // 
        //You can use the following additional simpleTypes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region GetChildCountTest
        /// <summary>
        ///  Test for GetChildCount method.
        /// </summary>
        [TestMethod()]
        public void ChildCountTest01() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);

            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 1 });
            Assert.AreEqual<int>(31, actual);
        }

        /// <summary>
        ///  Test for GetChildCount method.
        /// </summary>
        [TestMethod()]
        public void ChildCountTest02() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);

            int actual = reader.GetChildCount(new int[] { 1 });
            Assert.AreEqual<int>(2, actual);
        }

        /// <summary>
        ///  Test for GetChildCount method.
        /// </summary>
        [TestMethod()]
        public void ChildCountTest03() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);

            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 1, 1 });
            Assert.AreEqual<int>(3, actual); // should be 3
        }

        /// <summary>
        ///  Test for GetChildCount method.
        /// </summary>
        [TestMethod()]
        public void ChildCountTest04() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);

            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 2 });
            Assert.AreEqual<int>(25, actual);
        }

        /// <summary>
        ///  Test for GetChildCount method.
        /// </summary>
        [TestMethod()]
        public void ChildCountTest05() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);

            int actual = reader.GetChildCount(new int[] { 1, 2 });
            Assert.AreEqual<int>(27, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest01() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 1 });
            Assert.AreEqual<int>(31, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest02() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 1, 1 });
            Assert.AreEqual<int>(3, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest03() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 2 });
            Assert.AreEqual<int>(25, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest04() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 1, 1, 3 });
            Assert.AreEqual<int>(24, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest05() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 1, 1 });
            Assert.AreEqual<int>(25, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest06() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 2, 1 });
            Assert.AreEqual<int>(45, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest07() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 5, 1 });
            Assert.AreEqual<int>(26, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest08() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2 });
            Assert.AreEqual<int>(27, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest09() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 27, 1 });
            Assert.AreEqual<int>(20, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest10() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 27, 4 });
            Assert.AreEqual<int>(11, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        [TestMethod()]
        public void GetChildCountTest11() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 27, 22 });
            Assert.AreEqual<int>(21, actual);
        }

        /// <summary>
        /// Test for GetChildCount.
        /// </summary>
        /// <remarks>New Testament -> Revelation -> Chapter 22 -> Verse 5 -> 1 text param</remarks>
        [TestMethod()]
        public void GetChildCountTest12() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            int actual = reader.GetChildCount(new int[] { 1, 2, 27, 22, 5 });
            Assert.AreEqual<int>(1, actual); // there is one text param
        }

        [TestMethod()]
        public void GetChildCountTest13() {
            var reader = new BigXmlReader_Accessor(Common.PathTest6);
            int actual = reader.GetChildCount(new int[] { 1, 1, 1 });
            int expected = 0;
            Assert.AreEqual<int>(expected, actual);
        }
        #endregion

        #region NavigateToAddress tests
        /// <summary>
        /// Test for exception when navigating out of document.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.Xml.XmlException))]
        public void NavigateToAddressFailTest() {
            BigXmlReader reader = new BigXmlReader(Common.PathBible1);

            reader.NavigateToAddress(new int[] { 1, 10 });
            reader.Close();

            // Assert.AreEqual<bool>(true, reader.reader.EOF);
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest01() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 1, 2 }); // <book title="Exodus">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("book", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("Exodus", ((XmlNode)node.XmlNode).Attributes["title"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest02() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1 }); // <bible>
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("bible", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(0, ((XmlNode)node.XmlNode).Attributes.Count);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest03() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 1, 1, 1 }); // <chapter number="1">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("chapter", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("1", ((XmlNode)node.XmlNode).Attributes["number"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest04() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 1, 1, 1, 1 }); // <verse number="1">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("verse", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("1", ((XmlNode)node.XmlNode).Attributes["number"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest05() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            XmlReader r = reader.NavigateToAddress(new int[] { 1, 1, 1, 2 }); // <chapter number="2">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("chapter", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("2", ((XmlNode)node.XmlNode).Attributes["number"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest06() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 1, 1, 1, 20 }); // <verse number="20">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("verse", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("20", ((XmlNode)node.XmlNode).Attributes["number"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest07() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 2 }); // <testament value="New Testament">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("testament", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("New Testament", ((XmlNode)node.XmlNode).Attributes["value"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for navigation in xml document.
        /// </summary>
        [TestMethod()]
        public void NavigateToAddressTest08() {
            var reader = new BigXmlReader_Accessor(Common.PathBible1);
            var r = reader.NavigateToAddress(new int[] { 1, 2, 1, 1 }); // <chapter number="1">
            r.Read();
            var node = reader.CreateElement(r);

            Assert.AreEqual<string>("chapter", node.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<int>(1, ((XmlNode)node.XmlNode).Attributes.Count);
            Assert.AreEqual<string>("1", ((XmlNode)node.XmlNode).Attributes["number"].Value);

            reader.Close();
        }

        /// <summary>
        /// Test for NavigateToAddress expecting an exception.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void NavigateToAddressParameterTest() {
            BigXmlReader reader = new BigXmlReader(Common.PathBible1);
            reader.NavigateToAddress(new int[] { 1, -1, 2 });
        }
        #endregion

        #region CurrentAddressTests
        /// <summary>
        /// A test testing whether the current address is correct. Basic test.
        /// </summary>
        [TestMethod()]
        public void CurrentAddressTest01() {
            BigXmlReader reader = new BigXmlReader(Common.PathBible1);
            reader.NavigateToAddress(new int[] { 1, 1, 2 });

            Assert.IsTrue(new int[] { 1, 1, 2 }.SequenceEqual(reader.CurrentAddress));
        }

        /// <summary>
        /// A test testing whether the current address is correct. After GetNextElement() test.
        /// </summary>
        [TestMethod()]
        public void CurrentAddressTest02() {
            var reader = new BigXmlReader(Common.PathTest1);
            var r = reader.NavigateToAddress(new int[] { 1, 1, 1 });
            //reader.CreateElement(r);

            Assert.IsTrue(reader.CurrentAddress.SequenceEqual(new int[] { 1, 1, 1 }));

            reader.Close();

            r = reader.NavigateToAddress(new int[] { 1, 1, 2 });
            //reader.CreateElement(r);

            Assert.IsTrue(reader.CurrentAddress.SequenceEqual(new int[] { 1, 1, 2 }));

            //reader.GetNextElement();
            //Assert.IsTrue(reader.currentAddress.SequenceEqual(new int[] { 1, 1, 3, 4, 2 }));
        }
        #endregion

        #region ParseRangeTest
        /// <summary>
        ///A test for ParseRange
        ///</summary>
        [TestMethod()]
        [DeploymentItem("BigXmlReader.dll")]
        public void ParseRangeGoodStringTest() {
            string rangeString = "1-10,12-20";
            List<int> expected = new List<int>();
            for(int i = 1; i < 11; ++i) {
                expected.Add(i);
            }

            for(int i = 12; i < 21; ++i) {
                expected.Add(i);
            }

            IEnumerable<int> actual;
            actual = rangeString.ParseRange();
            Assert.AreEqual(expected.Count, actual.Count());
            Assert.IsTrue(expected.SequenceEqual(actual));

            rangeString = @"1-2,2,4-4,5";
            expected.Clear();
            expected.Add(1);
            expected.Add(2);
            expected.Add(4);
            expected.Add(5);

            actual = rangeString.ParseRange();
            Assert.AreEqual(expected.Count, actual.Count());
            Assert.IsTrue(expected.SequenceEqual(actual));
        }

        /// <summary>
        /// Test for parsing an empty string. Should return an empty collection.
        /// </summary>
        [TestMethod()]
        public void ParseEmptyRangeTest() {
            string rangeString = string.Empty;
            List<int> expected = new List<int>();

            IEnumerable<int> actual = rangeString.ParseRange();
            Assert.IsTrue(expected.SequenceEqual(actual));
        }

        /// <summary>
        /// Test for parsing a bad string. Should return an ArgumentException.
        /// </summary>
        [ExpectedException(typeof(System.ArgumentException))]
        [TestMethod()]
        public void ParseBadString1Test() {
            string rangeString = @"blabla";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [ExpectedException(typeof(System.ArgumentException))]
        [TestMethod()]
        public void ParseBadString2Test() {
            string rangeString = @"-1-2";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [ExpectedException(typeof(System.ArgumentException))]
        [TestMethod()]
        public void ParseBadString3Test() {
            string rangeString = @"-4--12,-5,-10";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [ExpectedException(typeof(System.ArgumentException))]
        [TestMethod()]
        public void ParseBadString4Test() {
            string rangeString = @"-10";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString5Test() {
            string rangeString = @"0";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString6Test() {
            string rangeString = @"-1";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString7Test() {
            string rangeString = @"-10--20";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString8Test() {
            string rangeString = @"1.2";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString9Test() {
            string rangeString = @"-";
            IEnumerable<int> actual = rangeString.ParseRange();
        }

        /// <summary>
        /// Test for parsing a bad range. Should return an ArgumentException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(System.ArgumentException))]
        public void ParseBadString10Test() {
            string rangeString = @"-A-1";
            IEnumerable<int> actual = rangeString.ParseRange();
        }
        #endregion

        #region Other tests
        /// <summary>
        /// Test for Close method.
        /// </summary>
        [TestMethod()]
        public void CloseTest() {
            BigXmlReader reader = new BigXmlReader(Common.PathBible1);
            reader.Open();

            // now reader should be opened
            Assert.IsTrue(reader.Opened == true);

            reader.Close();

            // after closing the reader these contracts should be true
            Assert.IsTrue(reader.Opened == false);
            Assert.IsTrue(reader.Path == Common.PathBible1);
        }
        #endregion

        #region GetChildNodesTest
        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes01Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1 }, "1-2");

            var book1 = nodes.ElementAt(0);
            var book2 = nodes.ElementAt(1);

            Assert.AreEqual<string>("book", book1.LocalName);
            Assert.AreEqual<string>("book", book2.LocalName);
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes02Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1 }, "1-2");

            Assert.AreEqual<int>(2, nodes.Count());
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes03Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1, 1 }, "1-31");

            Assert.AreEqual<int>(31, nodes.Count());
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes04Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1, 1 }, "1-5");

            Assert.AreEqual<int>(5, (from x in nodes where x != null select x).Count());
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes05Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1, 2 }, "1-25");

            Assert.AreEqual<int>(25, nodes.Count());
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes06Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1, 1 }, "1-3,5");

            Assert.AreEqual<int>(4, (from x in nodes where x != null select x).Count());

            Assert.AreEqual<string>("verse", nodes.ElementAt(0).LocalName);
            Assert.AreEqual<string>("number", ((XmlNode)nodes.ElementAt(0).XmlNode).Attributes[0].LocalName);
            Assert.AreEqual<string>("1", ((XmlNode)nodes.ElementAt(0).XmlNode).Attributes[0].Value);

            Assert.AreEqual<string>("verse", nodes.ElementAt(1).LocalName);
            Assert.AreEqual<string>("number", ((XmlNode)nodes.ElementAt(1).XmlNode).Attributes[0].LocalName);
            Assert.AreEqual<string>("2", ((XmlNode)nodes.ElementAt(1).XmlNode).Attributes[0].Value);

            Assert.AreEqual<string>("verse", nodes.ElementAt(2).LocalName);
            Assert.AreEqual<string>("number", ((XmlNode)nodes.ElementAt(2).XmlNode).Attributes[0].LocalName);
            Assert.AreEqual<string>("3", ((XmlNode)nodes.ElementAt(2).XmlNode).Attributes[0].Value);

            Assert.AreEqual<string>("verse", nodes.ElementAt(4).LocalName);
            Assert.AreEqual<string>("number", ((XmlNode)nodes.ElementAt(4).XmlNode).Attributes[0].LocalName);
            Assert.AreEqual<string>("5", ((XmlNode)nodes.ElementAt(4).XmlNode).Attributes[0].Value);

            Assert.IsNull(nodes.ElementAt(3));
        }

        /// <summary>
        /// Test for GetChildNodes.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes07Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 2, 27, 5 }, string.Empty);

            Assert.AreEqual<int>(14, nodes.Count());

            Assert.AreEqual<string>("verse", nodes.ElementAt(0).LocalName);
            Assert.AreEqual<string>("number", ((XmlNode)nodes.ElementAt(0).XmlNode).Attributes[0].LocalName);
            Assert.AreEqual<string>("1", ((XmlNode)nodes.ElementAt(0).XmlNode).Attributes[0].Value);
            // Assert.AreEqual<string>("And I saw in the right hand of him that sat on the throne a book written within and on the backside, sealed with seven seals.", nodes.ElementAt(0).Value);
        }

        /// <summary>
        /// Tries to get child nodes of the root element. Then checks if it gets the right
        /// elements by comparing their names and addresses.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes08Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1 }, string.Empty);

            int expected = 2;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);

            var node01 = nodes.ElementAt(0);
            Assert.IsTrue(node01.Address.SequenceEqual(new int[] { 1, 1 }));

            var node02 = nodes.ElementAt(1);
            Assert.IsTrue(node02.Address.SequenceEqual(new int[] { 1, 2 }));

            Assert.AreEqual<string>("categories", node01.Name);
            Assert.AreEqual<string>("stock", node02.Name);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 1. Then checks if it gets the right
        /// elements by comparing their names and addresses.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes09Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1 }, string.Empty);

            int expected = 2;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);

            var node01 = nodes.ElementAt(0);
            Assert.IsTrue(node01.Address.SequenceEqual(new int[] { 1, 1, 1 }));

            var node02 = nodes.ElementAt(1);
            Assert.IsTrue(node02.Address.SequenceEqual(new int[] { 1, 1, 2 }));

            Assert.AreEqual<string>("category", node01.Name);
            Assert.AreEqual<string>("category", node02.Name);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 2. Then checks if it gets the right
        /// elements by comparing their names and addresses.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes10Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 2 }, string.Empty);
            int expected = 2;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);

            var node01 = nodes.ElementAt(0);
            Assert.IsTrue(node01.Address.SequenceEqual(new int[] { 1, 2, 1 }));

            var node02 = nodes.ElementAt(1);
            Assert.IsTrue(node02.Address.SequenceEqual(new int[] { 1, 2, 2 }));

            Assert.AreEqual<string>("books", node01.Name);
            Assert.AreEqual<string>("cds", node02.Name);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 1, 1. Then checks if it gets the right
        /// elements by comparing their names and addresses.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes11Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1 }, string.Empty);
            int expected = 5;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);

            var node01 = nodes.ElementAt(0);
            Assert.IsTrue(node01.Address.SequenceEqual(new int[] { 1, 1, 1, 1 }));

            var node02 = nodes.ElementAt(1);
            Assert.IsTrue(node02.Address.SequenceEqual(new int[] { 1, 1, 1, 2 }));

            var node03 = nodes.ElementAt(2);
            Assert.IsTrue(node03.Address.SequenceEqual(new int[] { 1, 1, 1, 3 }));

            var node04 = nodes.ElementAt(3);
            Assert.IsTrue(node04.Address.SequenceEqual(new int[] { 1, 1, 1, 4 }));

            var node05 = nodes.ElementAt(4);
            Assert.IsTrue(node05.Address.SequenceEqual(new int[] { 1, 1, 1, 5 }));

            Assert.AreEqual<string>("item", node01.Name);
            Assert.AreEqual<string>("item", node02.Name);
            Assert.AreEqual<string>("item", node03.Name);
            Assert.AreEqual<string>("item", node04.Name);
            Assert.AreEqual<string>("item", node05.Name);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 2, 1, 2. Then checks if it gets the right
        /// elements by comparing their names and addresses.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes12Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 2, 1, 2 }, string.Empty);
            int expected = 1;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);

            var node01 = nodes.ElementAt(0);
            Assert.IsTrue(node01.Address.SequenceEqual(new int[] { 1, 2, 1, 2, 1 }));

            Assert.AreEqual<string>("title", node01.Name);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 2, 2, 2, 2. Then checks if it gets the right
        /// elements by comparing their names and addresses. Should throw XmlException because this address is out of scope of this document.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void GetChildNodes13Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 2, 2, 2, 2 }, string.Empty);
            //int expected = 0;
            //int actual = nodes.Count();
            //Assert.AreEqual<int>(expected, actual);
        }

        /// <summary>
        /// Tries to get child nodes of the element at address 1, 2, 2, 2, 3. Then checks if it gets the right
        /// elements by comparing their names and addresses. Should throw an exception.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void GetChildNodes14Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1, 2, 2, 2, 3 }, string.Empty);
            int expected = 0;
            int actual = nodes.Count();
            Assert.AreEqual<int>(expected, actual);
        }

        /// <summary>
        /// Tests argument validation - address.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetChildNodes15Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 0, 0, -1 }, string.Empty);
        }

        /// <summary>
        /// Tests argument validation - range.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void GetChildNodes16Test() {
            var reader = new BigXmlReader(Common.PathTest1);

            var nodes = reader.GetChildNodes(new int[] { 1 }, "aaa");
        }

        /// <summary>
        /// Tests getting elements that have namespaces defined.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes17Test() {
            var reader = new BigXmlReader(Common.PathTest4);

            var nodes = reader.GetChildNodes(new int[] { 1 }, string.Empty);
            Assert.AreEqual<int>(2, nodes.Count());

            var node1 = nodes.ElementAt(0);
            var node2 = nodes.ElementAt(1);

            Assert.AreEqual<string>("table", node1.LocalName);
            Assert.AreEqual<string>("h", node1.Prefix);
            Assert.AreEqual<string>("h:table", node1.Name);
            Assert.AreEqual<string>("http://www.w3.org/TR/html4/", node1.NamespaceURI);

            Assert.AreEqual<string>("table", node2.LocalName);
            Assert.AreEqual<string>("f", node2.Prefix);
            Assert.AreEqual<string>("f:table", node2.Name);
            Assert.AreEqual<string>("http://www.w3schools.com/furniture", node2.NamespaceURI);
        }

        /// <summary>
        /// Tests getting elements that have namespaces defined.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes18Test() {
            var reader = new BigXmlReader(Common.PathTest4);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1 }, string.Empty);
            Assert.AreEqual<int>(2, nodes.Count());

            var node1 = nodes.ElementAt(0);
            var node2 = nodes.ElementAt(1);

            Assert.AreEqual<string>("td", node1.LocalName);
            Assert.AreEqual<string>("h", node1.Prefix);
            Assert.AreEqual<string>("h:td", node1.Name);
            Assert.AreEqual<string>("http://www.w3.org/TR/html4/", node1.NamespaceURI);

            Assert.AreEqual<string>("td", node2.LocalName);
            Assert.AreEqual<string>("h", node2.Prefix);
            Assert.AreEqual<string>("h:td", node2.Name);
            Assert.AreEqual<string>("http://www.w3.org/TR/html4/", node2.NamespaceURI);
        }

        /// <summary>
        /// Tests getting elements that have namespaces defined.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes19Test() {
            var reader = new BigXmlReader(Common.PathTest4);

            var nodes = reader.GetChildNodes(new int[] { 1, 2, 4 }, string.Empty);
            Assert.AreEqual<int>(3, nodes.Count());

            var node1 = nodes.ElementAt(0);
            var node2 = nodes.ElementAt(1);
            var node3 = nodes.ElementAt(2);

            Assert.AreEqual<string>("name", node1.LocalName);
            Assert.AreEqual<string>("g", node1.Prefix);
            Assert.AreEqual<string>("g:name", node1.Name);
            Assert.AreEqual<string>("http://www.w3schools.com/geography", node1.NamespaceURI);

            Assert.AreEqual<string>("language", node2.LocalName);
            Assert.AreEqual<string>("g", node2.Prefix);
            Assert.AreEqual<string>("g:language", node2.Name);
            Assert.AreEqual<string>("http://www.w3schools.com/geography", node2.NamespaceURI);

            Assert.AreEqual<string>("width", node3.LocalName);
            Assert.AreEqual<string>("f", node3.Prefix);
            Assert.AreEqual<string>("f:width", node3.Name);
            Assert.AreEqual<string>("http://www.w3schools.com/furniture", node3.NamespaceURI);
        }

        /// <summary>
        /// Test getting child nodes of an element which has mixed content (text nodes and elements).
        /// </summary>
        [TestMethod()]
        public void GetChildNodes20Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            var nodes = reader.GetChildNodes(new int[] { 1, 1, 1, 1, 1 }, string.Empty);
            Assert.AreEqual<int>(3, nodes.Count());

            var node1 = nodes.ElementAt(0);
            var node2 = nodes.ElementAt(1);
            var node3 = nodes.ElementAt(2);

            Assert.IsTrue(node1.XmlNode.CreateNavigator().NodeType == XPathNodeType.Text);
            Assert.IsTrue(node2.XmlNode.CreateNavigator().NodeType == XPathNodeType.Element);
            Assert.IsTrue(node3.XmlNode.CreateNavigator().NodeType == XPathNodeType.Text);

            Assert.AreEqual<string>("In the beginning God created  ", node1.XmlNode.CreateNavigator().Value);
            Assert.AreEqual<string>("theheaven", node2.XmlNode.CreateNavigator().Name);
            Assert.AreEqual<string>(" and the earth.", node3.XmlNode.CreateNavigator().Value);
        }

        /// <summary>
        /// Test for GetChildNodes, checks the correctness of TotalChildCount property.
        /// </summary>
        [TestMethod()]
        public void GetChildNodes21Test() {
            var reader = new BigXmlReader(Common.PathBible1);

            IEnumerable<BigXmlNode> nodes = reader.GetChildNodes(new int[] { 1, 1 }, "1-2");

            var genesis = nodes.ElementAt(0); // Genesis
            var exodus = nodes.ElementAt(1); // Exodus

            Assert.AreEqual<string>("book", genesis.LocalName);
            Assert.AreEqual<string>("book", exodus.LocalName);

            Assert.AreEqual<int>(50, genesis.TotalChildCount);
            Assert.AreEqual<int>(40, exodus.TotalChildCount);
        }
        #endregion

        #region Schema validation
        ///// <summary>
        ///// Test for inner schema validation.
        ///// </summary>
        //[TestMethod]
        //public void InnerSchemaValidationBigXmlReaderConstructorTest()
        //{
        //    BigXmlReader reader = new BigXmlReader(this.path, ValidationType.Schema);
        //    reader.ValidateXsd();
        //}

        /// <summary>
        /// Test for external schema validation.
        /// </summary>
        //[TestMethod()]
        //public void ExternalSchemaValidationBigXmlReaderConstructorTest() {
        //    XmlSchemaSet schemaSet = new XmlSchemaSet();
        //    schemaSet.Add(null, Common.PathShiporderXsd);

        //    BigXmlReader reader = new BigXmlReader(Common.PathShiporder, schemaSet);
        //    reader.ValidationEvent += new ValidationEventHandler(reader_ValidationEventHandler);
        //    reader.ValidateXsd();
        //}

        ///// <summary>
        ///// Test for external schema validation constructor.
        ///// </summary>
        //[TestMethod()]
        //public void ExternalSchemaValidationBigXmlReaderConstructorTest2() {
        //    BigXmlReader reader = new BigXmlReader(Common.PathShiporder, ValidationType.Schema);
        //    reader.ValidationEvent += new ValidationEventHandler(reader_ValidationEventHandler);
        //    reader.ValidateXsd();
        //}

        ///// <summary>
        ///// Test for internal xsd schema validation.
        ///// </summary>
        //[TestMethod()]
        //public void InlineSchemaValidationTest() {
        //    BigXmlReader reader = new BigXmlReader(Common.PathShiporder, ValidationType.Schema);
        //    reader.ValidationEvent += new ValidationEventHandler(reader_ValidationEventHandler);
        //    reader.ValidateXsd();
        //}

        ///// <summary>
        ///// Validation event handler.
        ///// </summary>
        ///// <param name="sender">The object where the event handler is attached.</param>
        ///// <param name="args">The event args.</param>
        //private void reader_ValidationEventHandler(object sender, ValidationEventArgs args) {
        //    if(args.Severity == XmlSeverityType.Warning) {
        //        Debug.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
        //    } else {
        //        Debug.WriteLine("\tValidation error: " + args.Message);
        //    }
        //}
        #endregion

        #region Xml well-formedness tests
        /// <summary>
        /// Tests document's well formedness. This document is not well formed so it throws an exception.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void CheckWellFormedness01Test() {
            var reader = new BigXmlReader(Common.PathTest2);
            reader.CheckWellFormedness();
        }

        /// <summary>
        /// Tests well formedness of a well formed document. Should succeed hence no exceptions.
        /// </summary>
        [TestMethod()]
        public void CheckWellFormedness02Test() {
            var reader = new BigXmlReader(Common.PathTest1);
            reader.CheckWellFormedness();
        }
        #endregion

        #region Damaged file tests
        /// <summary>
        /// Read root element from not well formed document. Should throw <see cref="XmlException"/>.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void GetRootFromDamagedFileTest() {
            var reader = new BigXmlReader(Common.PathTest2);
            var root = reader.GetRootElement();
            //Assert.IsNotNull(root);
            //Assert.AreEqual<string>("root", root.XmlNode.CreateNavigator().Name);
        }
        #endregion

        #region GetRootElementTests
        /// <summary>
        /// Test to read document root.
        /// </summary>
        [TestMethod()]
        public void GetRootElementTest() {
            var reader = new BigXmlReader(Common.PathTest1);

            var root = reader.GetRootElement();
            Assert.IsNotNull(root);
            Assert.AreEqual<string>("root", root.XmlNode.CreateNavigator().Name);
            Assert.IsTrue(root.Address.SequenceEqual(new int[] { 1 }));
            Assert.AreEqual(37, reader.TotalNodeCount);
        }

        /// <summary>
        /// Test to get the root element of a correct xml file.
        /// </summary>
        [TestMethod()]
        public void GetRootElementTest01() {
            var reader = new BigXmlReader(Common.PathTest1);
            var rootElement = reader.GetRootElement();

            Assert.IsNotNull(rootElement);
            Assert.AreEqual<string>("root", rootElement.Name);
        }

        /// <summary>
        /// Test to get the root element of an incorrect xml file. There is no root element
        /// so GetRootElement should throw an XmlException.
        /// </summary>
        [TestMethod()]
        [ExpectedException(typeof(XmlException))]
        public void GetRootElementTest02() {
            var reader = new BigXmlReader(Common.PathTest3);
            var rootElement = reader.GetRootElement();
        }
        #endregion

        #region WriteChildNodesFromAddress tests
        [TestMethod()]
        public void WriteChildNodesFromAddressTest01() {
            var reader = new BigXmlReader(Common.PathTest1);

            var sb = new StringBuilder();
            var w = XmlWriter.Create(sb);

            w.WriteStartElement("root");
            reader.WriteChildNodesFromAddress(new int[] { 1, 1 }, w, null);
            w.WriteEndElement();

            w.Close();

            string xml = sb.ToString();
            Assert.IsTrue(!string.IsNullOrEmpty(xml));
        }
        #endregion

        #region GetAllFromAddress tests
        [TestMethod()]
        public void GetAllFromAddressTest01() {
            var reader = new BigXmlReader(Common.PathTest8);
            var root = reader.GetAllFromAddress(new int[] { 1, 1 });
            Assert.IsNotNull(root);
            Assert.AreEqual<int>(2, root.TotalChildCount);
            Assert.IsFalse(root.Modified);
            //Assert.AreEqual<int>(21, store.Count);
        }
        #endregion

        #region Test
        [TestMethod()]
        public void XPathTest() {
            var model = ModelFactory.CreateXmlModel();
            model.Open(Common.PathTest1);

            var root = model.GetRootElement() as BigXmlNodeInternal;
            model.ExpandNode(root);

            var categories = root.ChildNodes[0];
            var stock = root.ChildNodes[1];

            var navigator = root.XmlNode.CreateNavigator();
            var res = navigator.Select("stock");
        }
        #endregion
    }
}